package com.minelx.datamicroscope.core.query;

import com.alibaba.fastjson.JSONObject;
import com.minelx.datamicroscope.core.values.CommonField;
import com.minelx.sqlstructures.core.ColumnType;
import com.minelx.sqlstructures.statements.clause.Field;
import com.minelx.table.core.Table;
import com.minelx.table.core.series.Series;

import java.util.List;
import java.util.Objects;

import static java.util.stream.Collectors.toList;
import static java.util.stream.IntStream.range;

public class AliasedKey {

	private final String alias;

	private final CommonField key;

	private AliasedKey(String alias, CommonField key) {
		this.alias = alias;
		this.key = key;
	}

	public Field asSqlField() {
		return Field.as(key.name(), getAlias());
	}

	public CommonField getKey() {
		return key;
	}

	public String getAlias() {
		return alias;
	}

	public Table dropNaN(Table values) {
		return dropNaN(values, key, getAlias());
	}

	@Override
	public String toString() {
		return "AliasedKey{" +
				"alias='" + alias + '\'' +
				", key=" + key +
				'}';
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;
		AliasedKey that = (AliasedKey) o;
		return alias.equals(that.alias) && key.equals(that.key);
	}

	@Override
	public int hashCode() {
		return Objects.hash(alias, key);
	}

	public static AliasedKey create(String alias, CommonField key) {
		return new AliasedKey(alias, key);
	}

	public static List<AliasedKey> create(List<String> aliases, List<CommonField> keys) {
		return range(0, keys.size())
				.mapToObj(at -> create(aliases.get(at), keys.get(at)))
				.collect(toList());
	}

	public static Table dropNaN(Table values, List<AliasedKey> atColumns) {
		Table result = values;
		for (AliasedKey atColumn : atColumns) {
			result = atColumn.dropNaN(values);
		}
		return result;
	}

	public static Table dropNaN(Table values, CommonField key, String alias) {
		if (ColumnType.from(key.structure().getType()) == ColumnType.INT) {
			Series<String> column = values.column(alias);
			return values.rows(column.mapSource(each -> !each.isEmpty()));
		}
		return values;
	}

	public static AliasedKey from(JSONObject aliasedKeyAsJSON) {
		CommonField key = CommonField.from(aliasedKeyAsJSON.getString("key"));
		return create(aliasedKeyAsJSON.getString("alias"), key);
	}
}
